<?php

namespace app\controller;

use app\BaseController;
use app\model\VipModel;
use think\Request;
use think\Response;
use think\facade\Db;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use PhpOffice\PhpSpreadsheet\Writer\Csv;
use app\common\Snowflake;
use PhpOffice\PhpSpreadsheet\IOFactory;
use app\validate\VipValidate;
use League\Csv\Reader;

class Vip extends BaseController {
    // 新增 VIP
    public function create()
    {
        $data = $this->request->post();
        $validate = new VipValidate();
        if (!$validate->check($data)) {
            return json([
                'code' => 1,
                'msg' => $validate->getError(),
                'data' => []
            ]);
        }

        $snowflake = new Snowflake(1, 1);
        $vipid = $snowflake->nextId();
        $data['vipid'] = $vipid;

        $insertData = [
            'vipid' => $vipid,
            'title' => $data['title'],
            'image_url' => $data['image_url'],
            'original_price' => $data['original_price'],
            'discount_price' => $data['discount_price'],
            'min_price' => $data['min_price'],
            'duration' => $data['duration'],
            'purchase_limit' => $data['purchase_limit'],
            'sort' => isset($data['sort']) ? $data['sort'] : 0,
            'is_publish' => isset($data['is_publish']) ? $data['is_publish'] : 0,
            'status' => isset($data['status']) ? $data['status'] : 'offline',
            'created_at' => date('Y-m-d H:i:s'),
        ];

        $id = Db::name('vip')->insertGetId($insertData);
        if ($id) {
            return json([
                'code' => 0,
                'msg' => '新增 VIP 成功',
                'data' => ['id' => $id]
            ]);
        } else {
            return json([
                'code' => 1,
                'msg' => '新增 VIP 失败',
                'data' => []
            ]);
        }
    }

    // 编辑 VIP
    public function update($id)
    {
        $data =  $this->request->post();
        $validate = new VipValidate();
        if (!$validate->check($data)) {
            return json([
                'code' => 1,
                'msg' => $validate->getError(),
                'data' => []
            ]);
        }


        $result = Db::name('vip')->where('id', $id)->update($data);
        if ($result) {
            return json([
                'code' => 0,
                'msg' => 'ok',
                'data' => []
            ]);
        } else {
            return json([
                'code' => 1,
                'msg' => '编辑 VIP 失败',
                'data' => []
            ]);
        }
    }

    // VIP 列表
    public function list()
    {
        $vipid = $this->request->param('vipid');
        $title = $this->request->param('title');
        $status = $this->request->param('status');
        $page = $this->request->param('page', 1);
        $limit = $this->request->param('limit', 10);

        $query = Db::name('vip');
        if ($vipid) {
            $query->where('vipid', $vipid);
        }
        if ($title) {
            $query->where('title', 'like', "%{$title}%");
        }
        if ($status && $status != 'all') {
            $query->where('status', $status);
        }

        $list = $query->field('id, vipid,title, image_url, original_price, discount_price, min_price,duration,purchase_limit,sort,is_publish,status,update_time')
            ->page($page, $limit)
            ->select();

        $total = $query->count();

        return json([
            'code' => 0,
            'msg' => 'ok',
            'data' => [
                'list' => $list,
                'total' => $total
            ]
        ]);
    }

    // 删除 VIP
    public function delete($id)
    {
        $result = Db::name('vip')->where('id', $id)->delete();
        if ($result) {
            return json([
                'code' => 0,
                'msg' => '删除 VIP 成功',
                'data' => []
            ]);
        } else {
            return json([
                'code' => 1,
                'msg' => '删除 VIP 失败',
                'data' => []
            ]);
        }
    }

    // 导出数据
    public function export()
    {
        $vipid = $this->request->param('vipid');
        $title = $this->request->param('title');
        $status = $this->request->param('status');
        $fileType = $this->request->param('file_type', 'csv'); // 默认导出为 CSV

        $query = Db::name('vip');
        if ($vipid) {
            $query->where('vipid', $vipid);
        }
        if ($title) {
            $query->where('title', 'like', "%{$title}%");
        }
        if ($status && $status != 'all') {
            $query->where('status', $status);
        }

        $list = $query->select();
        $spreadsheet = new Spreadsheet();
        $sheet = $spreadsheet->getActiveSheet();

        $csvData = [];
        $header = ['id', 'vipid', 'title', 'image_url', 'original_price', 'discount_price', 'min_price', 'duration', 'purchase_limit', 'sort', 'is_publish', 'status', 'update_time'];
        $sheet->fromArray([$header], null, 'A1');

        $rowIndex = 2;
        foreach ($list as $item) {
            $row = [];
            foreach ($header as $field) {
                $row[] = $item[$field];
            }
            $sheet->fromArray([$row], null, 'A' . $rowIndex);
            $rowIndex++;
        }

        $date = date('Ymd');
        $filename = $date . 'vipexport';

        if ($fileType === 'csv') {
            $writer = new Csv($spreadsheet);
            $filename .= '.csv';
            header('Content-Type: text/csv');
        } else {
            $writer = new Xlsx($spreadsheet);
            $filename .= '.xlsx';
            header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        }

        header('Content-Disposition: attachment;filename="' . $filename . '"');
        header('Cache-Control: max-age=0');

        $writer->save('php://output');
    }


    public function import(Request $request): Response
    {
        // 1. 文件上传校验
        $file = $request->file('file');
        if (!$file) return json(['code' => 1, 'msg' => '请选择文件']);

        $allowExt = ['csv', 'txt', 'xls', 'xlsx'];
        $ext = strtolower($file->getOriginalExtension());
        if (!in_array($ext, $allowExt)) {
            return json(['code' => 1, 'msg' => "仅支持{$allowExt}格式"]);
        }

        // 2. 安全存储文件（使用runtime临时目录）
        $savePath = runtime_path('import/') . date('Ymd/');
        if (!is_dir($savePath)) mkdir($savePath, 0755, true);

        $filename = uniqid() . '.' . $ext;
        $file->move($savePath, $filename);
        $filePath = $savePath . $filename;

        try {
            // 3. 解析文件内容
            $rows = $this->parseFile($filePath, $ext);
            if (empty($rows)) return json(['code' => 1, 'msg' => '文件无数据']);

            // 4. 数据处理与导入
            $success = 0;
            $errors = [];
            $snowflake = new Snowflake(1, 1); // 雪花ID生成器

            Db::startTrans();
            foreach ($rows as $rowNum => $row) {
                try {
                    // 基础数据转换（处理空值/类型）
                    $data = $this->convertRowData($row, $rowNum + 2, $snowflake);

                    // 数据验证（使用VipValidate的import场景）
                    $validate = new VipValidate();
                    if (!$validate->scene('import')->check($data)) {
                        throw new \Exception($validate->getError());
                    }

                    // 唯一性校验（vipid唯一）
                    if (Db::name('vip')->where('vipid', $data['vipid'])->find()) {
                        throw new \Exception("VIPID已存在: {$data['vipid']}");
                    }

                    // 写入数据库
                    $id = Db::name('vip')->insertGetId($data);
                    if ($id) $success++;

                } catch (\Exception $e) {
                    $errors[] = [
                        'row' => $rowNum + 2, // 行号从第2行开始（第1行表头）
                        'msg' => $e->getMessage()
                    ];
                }
            }

            Db::commit();
            @unlink($filePath); // 清理临时文件

            return json([
                'code' => 0,
                'msg' => "导入完成，成功{$success}条，失败" . count($errors) . "条",
                'data' => ['errors' => $errors]
            ]);

        } catch (\Exception $e) {
            Db::rollback();
            @unlink($filePath);
            return json(['code' => 1, 'msg' => "系统错误：{$e->getMessage()}"]);
        }
    }

    /**
     * 文件解析器（支持多格式）
     */
    private function parseFile($filePath, $ext): array
    {
        $rows = [];
        switch ($ext) {
            case 'csv':
            case 'txt':
                $csv = Reader::createFromPath($filePath);
                $csv->setDelimiter($ext === 'txt' ? "\t" : ',');
                $rows = $csv->getRecords();
                break;

            case 'xls':
            case 'xlsx':
                $spreadsheet = IOFactory::load($filePath);
                $rows = $spreadsheet->getActiveSheet()->toArray(null, true, true, true);
                break;
        }

        // 清理空行并转换为关联数组
        $header = array_map('trim', array_shift($rows));
        return array_filter(array_map(
            fn($row) => array_combine($header, $row),
            $rows
        ), fn($row) => !empty(array_filter($row)));
    }

    /**
     * 行数据转换（含类型校验）
     */
    private function convertRowData(array $row, int $rowNum, Snowflake $snowflake): array
    {
        // 基础字段处理（默认值+类型转换）
        $data = [
            'title' => trim($row['标题'] ?? '') ?: throw new \Exception('标题为空'),
            'image_url' => trim($row['商品图URL'] ?? '') ?: throw new \Exception('商品图URL为空'),
            'original_price' => $this->parsePrice($row['原价'] ?? 0, $rowNum),
            'discount_price' => $this->parsePrice($row['优惠价'] ?? 0, $rowNum),
            'min_price' => $this->parsePrice($row['最低价'] ?? 0, $rowNum),
            'duration' => (int)($row['持续时间（天）'] ?? 0) ?: throw new \Exception('持续时间必须为正整数'),
            'purchase_limit' => (int)($row['可购买次数'] ?? 0) ?: 0,
            'sort' => (int)($row['排序'] ?? 0),
            'is_publish' => $this->parseBool($row['是否发布'] ?? 0, $rowNum),
            'status' => $this->parseStatus($row['状态'] ?? 'offline', $rowNum),
            'created_at' => date('Y-m-d H:i:s')
        ];

        // VIPID处理（文件有则校验，无则生成）
        $data['vipid'] = trim($row['雪花ID'] ?? '');
        if (empty($data['vipid'])) {
            $data['vipid'] = $snowflake->nextId();
        } else if (!is_numeric($data['vipid']) || strlen($data['vipid']) > 18) {
            throw new \Exception('雪花ID格式错误（需18位数字）');
        }

        return $data;
    }

    /**
     * 价格字段解析（保留2位小数）
     */
    private function parsePrice($value, int $rowNum): string
    {
        if (!is_numeric($value)) throw new \Exception("价格格式错误（行{$rowNum}）");
        $price = sprintf('%.2f', $value);
        if ($price < 0) throw new \Exception("价格不能为负数（行{$rowNum}）");
        return $price;
    }

    /**
     * 布尔值解析（支持多种输入格式）
     */
    private function parseBool($value, int $rowNum): int
    {
        $map = ['是'=>1, '否'=>0, '1'=>1, '0'=>0, 'true'=>1, 'false'=>0];
        $value = strtolower(trim($value));
        if (!isset($map[$value])) throw new \Exception("是否发布格式错误（行{$rowNum}）");
        return $map[$value];
    }

    /**
     * 状态字段解析（严格校验枚举）
     */
    private function parseStatus($value, int $rowNum): string
    {
        $value = strtolower(trim($value));
        if (!in_array($value, ['online', 'offline'])) {
            throw new \Exception("状态错误（仅支持online/offline，行{$rowNum}）");
        }
        return $value;
    }
}